package 方法句柄;

/*public MethodHandle findConstructor​(类<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException
生成一个方法句柄，该句柄使用指定类型的构造函数创建对象并对其进行初始化。 方法句柄的参数类型将是构造函数的参数类型，而返回类型将是对构造函数类的引用。 
查找对象必须可以访问构造函数及其所有参数类型。
请求的类型必须具有返回类型void 。 （这与JVM对构造函数类型描述符的处理一致。）

当且仅当构造函数的变量arity修饰符位（ 0x0080 ）已设置时，返回的方法句柄才会有variable arity 。

如果调用返回的方法句柄，则初始化构造函数的类（如果尚未初始化）。

参数
refc - 从中访问方法的类或接口
type - 方法的类型，省略了receiver参数，以及void返回类型
结果: 所需的方法句柄
异常
NoSuchMethodException - 如果构造函数不存在
IllegalAccessException - 如果访问检查失败或者方法的变量arity修饰符位已设置且 asVarargsCollector失败
SecurityException - 如果存在安全管理器且 refuses access
NullPointerException - 如果任何参数为null

例：
*/

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;

import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class findConstructor用法 {

	public static void main(String[] args) throws Throwable{
		//生成一个ArrayList.class方法句柄，该句柄使用指定类型(Collection.class)的构造函数创建对象并对其进行初始化
		MethodHandle MH_newArrayList = publicLookup().findConstructor(ArrayList.class,
				methodType(void.class, Collection.class));
		Collection orig = Arrays.asList("x", "y");
		Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
		System.out.println("MH_newArrayList="+MH_newArrayList.toString());//MH_newArrayList=MethodHandle(Collection)ArrayList
		System.out.println("orig="+orig+", copy="+copy);//orig=[x, y], copy=[x, y]
		//assert (orig != copy);
		//assertEquals(orig, copy);
		// a variable-arity constructor:
		
		//生成一个ProcessBuilder.class方法句柄，该句柄使用指定类型(String[].class)的构造函数创建对象并对其进行初始化
		MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(ProcessBuilder.class,
				methodType(void.class, String[].class));
		ProcessBuilder pb = (ProcessBuilder) MH_newProcessBuilder.invoke("xx", "yy", "zz");
		System.out.println(MH_newProcessBuilder.toString());//MethodHandle(String[])ProcessBuilder
		System.out.println(pb.command().toString());//[xx, yy, zz]
		//assertEquals("[x, y, z]", pb.command().toString());
	}
}
